package com.supermap.desktop.develop.workspacemigration.migration;

import com.supermap.data.*;
import com.supermap.desktop.core.Application;
import com.supermap.desktop.core.Interface.IOutput;
import com.supermap.desktop.develop.workspacemigration.constants.SQLConstants;
import com.supermap.desktop.develop.workspacemigration.internalhelpers.InternalHelper;
import com.supermap.desktop.develop.workspacemigration.internalhelpers.SQLHelper;
import com.supermap.desktop.develop.workspacemigration.migration.events.MigrateSteppedEvent;

import javax.swing.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;

public class PG2DMDBWorkspaceMigration extends DBWorkspaceMigration {

    public PG2DMDBWorkspaceMigration(String srcIP, String srcPort, String srcDatabaseName,
                                     String srcUserName, String srcPassword, EngineType srcEngineType,
                                     String tarIP, String tarPort, String tarDatabaseName,
                                     String tarUserName, String tarPassword, EngineType tarEngineType, boolean isBatchMigration) {
        this(srcIP, srcPort, srcDatabaseName, srcUserName, srcPassword, srcEngineType, "",
                tarIP, tarPort, tarDatabaseName, tarUserName, tarPassword, tarEngineType, isBatchMigration);
    }

    public PG2DMDBWorkspaceMigration(String srcIP, String srcPort, String srcDatabaseName, String srcUserName,
                                     String srcPassword, EngineType srcEngineType, String srcWorkspaceName,
                                     String tarIP, String tarPort, String tarDatabaseName,
                                     String tarUserName, String tarPassword, EngineType tarEngineType, boolean isBatchMigration) {
        super(srcIP, srcPort, srcDatabaseName, srcUserName, srcPassword, srcEngineType, srcWorkspaceName,
                tarIP, tarPort, tarDatabaseName, tarUserName, tarPassword, tarEngineType, isBatchMigration);
    }

    @Override
    protected void initWorkspacesCore() {
        IOutput output = Application.getActiveApplication().getOutput();

        boolean isBatchMigration = isBatchMigration();
        String srcWorkspaceName = getSrcWorkspaceName();
        if (!isBatchMigration && (srcWorkspaceName == null || srcWorkspaceName.equals(""))) {
            output.output("非批量操作且没有选择要迁移的工作空间，若非批量操作请务必选择需要迁移的工作空间！");
            return;
        }

        try {
            ArrayList<String> srcWorkspaceNames = new ArrayList<>();

            if (isBatchMigration) {
                srcWorkspaceNames.addAll(querySrcWorkspaceNames());
            } else {
                srcWorkspaceNames.add(srcWorkspaceName);
            }

            ArrayList<Workspace> srcWorkspaces = getSrcWorkspaces();
            for (String workspaceName : srcWorkspaceNames) {
                WorkspaceConnectionInfo workspaceConnectionInfo = new WorkspaceConnectionInfo();
                workspaceConnectionInfo.setServer(getSrcIP());
                workspaceConnectionInfo.setDatabase(getSrcDatabaseName());
                workspaceConnectionInfo.setUser(getSrcUserName());
                workspaceConnectionInfo.setPassword(getSrcPassword());
                workspaceConnectionInfo.setType(getWorkspaceType(getSrcEngineType()));
                workspaceConnectionInfo.setName(workspaceName);
                Workspace workspace = new Workspace();
                workspace.setCaption(workspaceName);
                if (workspace.open(workspaceConnectionInfo)) {
                    srcWorkspaces.add(workspace);
                } else {
                    output.output("连接【" + workspaceConnectionInfo.getName() + "】工作空间失败！请检查连接参数是否正确");
                }
            }

            ArrayList<Workspace> tarWorkspaces = getTarWorkspaces();
            for (int i = 0; i < srcWorkspaces.size(); i++) {
                tarWorkspaces.add(new Workspace());
            }
        } catch (Exception e) {
            output.output(e);
        }
    }

    @Override
    protected boolean migrateDatasources(ArrayList<Workspace> srcWorkspaces, ArrayList<Workspace> tarWorkspaces) {
        IOutput output = Application.getActiveApplication().getOutput();
        boolean migrateResult = false;

        try {
            if (migratedDatasources == null) {
                migratedDatasources = new HashMap<>();
            }

            String ip = getTarIP();
            String port = getTarPort();
            String username = getTarUserName();
            String password = getTarPassword();
            EngineType tarEngineType = getTarEngineType();
            EngineType srcEngineType = getSrcEngineType();

            for (int i = 0; i < srcWorkspaces.size(); i++) {
                Workspace srcWorkspace = srcWorkspaces.get(i);
                Workspace tarWorkspace = tarWorkspaces.get(i);

                Datasources datasources = srcWorkspace.getDatasources();
                for (int j = 0; j < datasources.getCount(); j++) {
                    Datasource srcDatasource = datasources.get(j);
                    String datasourceAlias = srcDatasource.getAlias();

                    if (srcEngineType == srcDatasource.getEngineType()) {
                        if (!migratedDatasources.containsKey(datasourceAlias)) {
                            String tarDatasourceName = InternalHelper.getAvailableUserName(datasourceAlias);
                            if (tarEngineType == EngineType.DM) {
                                if (SQLHelper.createDMDatasourceUser(ip, port, username, password, tarDatasourceName)) {
                                    output.output("达梦数据库新建用户失败！");
                                    int tempCount = srcDatasource.getDatasets().getCount();
                                    processedSubTasksCount += tempCount;
                                    processedTasksCount += tempCount;
                                    fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                                            (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                                            "迁移【" + srcDatasource.getAlias() + "】数据源失败！", "migrateDatasources", false));
                                    continue;
                                }
                            }

                            String tablespaceName = SQLConstants.SuperMap.concat("_").concat(tarDatasourceName.toUpperCase());
                            DatasourceConnectionInfo tarDatasourceConnectionInfo = new DatasourceConnectionInfo();
                            tarDatasourceConnectionInfo.setEngineType(EngineType.DM);
                            tarDatasourceConnectionInfo.setServer(ip.concat(":").concat(port));
                            tarDatasourceConnectionInfo.setUser(tablespaceName);
                            tarDatasourceConnectionInfo.setPassword(tablespaceName);
                            tarDatasourceConnectionInfo.setAlias(datasourceAlias);
                            Datasource tarDatasource = tarWorkspace.getDatasources().create(tarDatasourceConnectionInfo);
                            migratedDatasources.put(datasourceAlias, tarDatasourceConnectionInfo);

                            if (tarDatasource == null) {
                                output.output("达梦数据源新建失败！----" + datasourceAlias);
                                int tempCount = srcDatasource.getDatasets().getCount();
                                processedSubTasksCount += tempCount;
                                processedTasksCount += tempCount;
                                fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                                        (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                                        "迁移【" + srcDatasource.getAlias() + "】数据源失败！", "migrateDatasources", false));
                                continue;
                            }

                            Datasets srcDatasets = srcDatasource.getDatasets();
                            for (int k = 0; k < srcDatasets.getCount(); k++) {
                                Dataset srcDataset = srcDatasets.get(k);
                                String srcDatasetName = srcDataset.getName();
                                SteppedListener copyDatasetSteppedListener = (steppedEvent) -> fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                                        steppedEvent.getPercent(), 0, "迁移工作空间", "迁移总进度",
                                        "迁移【" + srcDatasetName + "@" + datasourceAlias + "】 数据集中......", "migrateDatasources", false));
                                tarDatasource.addSteppedListener(copyDatasetSteppedListener);
                                Dataset tarDataset = tarDatasource.copyDataset(srcDataset, srcDatasetName, srcDataset.getEncodeType());
                                tarDatasource.removeSteppedListener(copyDatasetSteppedListener);
                                if (tarDataset == null) {
                                    output.output("拷贝源数据集到目标达梦数据集失败！----" + srcDatasetName);
                                } else {
                                    migrateResult = true;
                                }
                                processedSubTasksCount++;
                                processedTasksCount++;
                            }
                        } else {
                            DatasourceConnectionInfo tarDatasourceConnectionInfo = migratedDatasources.get(datasourceAlias);
                            if (tarWorkspace.getDatasources().open(tarDatasourceConnectionInfo) == null) {
                                output.output("迁移【" + datasourceAlias + "】数据源失败！");
                            }
                        }
                    } else {
                        DatasourceConnectionInfo datasourceConnectionInfo = srcDatasource.getConnectionInfo();
                        if (tarWorkspace.getDatasources().open(datasourceConnectionInfo) == null) {
                            output.output("迁移【" + datasourceConnectionInfo.getAlias() + "】数据源失败！");
                        }
                    }
                }
            }
        } catch (Exception e) {
            output.output(e);
            return migrateResult;
        } finally {
            if (migratedDatasources != null) {
                migratedDatasources.clear();
                migratedDatasources = null;
            }
        }

        return migrateResult;
    }

    @Override
    protected boolean migrateResources(ArrayList<Workspace> srcWorkspaces, ArrayList<Workspace> tarWorkspaces) {
        IOutput output = Application.getActiveApplication().getOutput();
        boolean migrateResult = false;

        try {
            for (int i = 0; i < srcWorkspaces.size(); i++) {
                Workspace srcWorkspace = srcWorkspaces.get(i);
                Workspace tarWorkspace = tarWorkspaces.get(i);
                String srcWorkspaceCaption = srcWorkspace.getCaption();

                Resources srcResources = srcWorkspace.getResources();
                Resources tarResources = tarWorkspace.getResources();
                String migrationTempFolderPath = InternalHelper.getMigrationTempFolderPath();

                fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                        (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                        "迁移【" + srcWorkspace.getCaption() + "】工作空间的填充符号库中......", "migrateResources", false));

                String fillLibraryTempFilePath = migrationTempFolderPath.concat("/").concat(UUID.randomUUID().toString()).concat(".bru");
                if (!srcResources.getFillLibrary().toFile(fillLibraryTempFilePath)) {
                    output.output("导出【" + srcWorkspaceCaption + "】工作空间的填充符号库失败！");
                } else {
                    if (!tarResources.getFillLibrary().fromFile(fillLibraryTempFilePath)) {
                        output.output("迁移【" + srcWorkspaceCaption + "】工作空间的填充符号库失败！");
                    } else {
                        migrateResult = true;
                    }
                }

                processedSubTasksCount++;
                processedTasksCount++;

                fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                        (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                        "迁移【" + srcWorkspace.getCaption() + "】工作空间的线符号库中......", "migrateResources", false));

                String lineLibraryTempFilePath = migrationTempFolderPath.concat("/").concat(UUID.randomUUID().toString()).concat(".lsl");
                if (!srcResources.getLineLibrary().toFile(lineLibraryTempFilePath)) {
                    output.output("导出【" + srcWorkspaceCaption + "】工作空间的线符号库失败！");
                } else {
                    if (!tarResources.getLineLibrary().fromFile(lineLibraryTempFilePath)) {
                        output.output("迁移【" + srcWorkspaceCaption + "】工作空间的线符号库失败！");
                    } else {
                        migrateResult = true;
                    }
                }

                processedSubTasksCount++;
                processedTasksCount++;

                fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                        (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                        "迁移【" + srcWorkspace.getCaption() + "】工作空间的点符号库中......", "migrateResources", false));

                String markerLibraryTempFilePath = migrationTempFolderPath.concat("/").concat(UUID.randomUUID().toString()).concat(".sym");
                if (!srcResources.getMarkerLibrary().toFile(markerLibraryTempFilePath)) {
                    output.output("导出【" + srcWorkspaceCaption + "】工作空间的点符号库失败！");
                } else {
                    if (!tarResources.getMarkerLibrary().fromFile(markerLibraryTempFilePath)) {
                        output.output("迁移【" + srcWorkspaceCaption + "】工作空间的点符号库失败！");
                    } else {
                        migrateResult = true;
                    }
                }

                processedSubTasksCount++;
                processedTasksCount++;
            }
        } catch (Exception e) {
            Application.getActiveApplication().getOutput().output(e);
            return migrateResult;
        } finally {
            SwingUtilities.invokeLater(InternalHelper::clearMigrationTempResources);
        }

        return migrateResult;
    }

    @Override
    protected boolean migrateMaps(ArrayList<Workspace> srcWorkspaces, ArrayList<Workspace> tarWorkspaces) {
        try {
            for (int i = 0; i < srcWorkspaces.size(); i++) {
                Workspace srcWorkspace = srcWorkspaces.get(i);
                Workspace tarWorkspace = tarWorkspaces.get(i);

                String srcWorkspaceCaption = srcWorkspace.getCaption();
                Maps srcMaps = srcWorkspace.getMaps();
                Maps tarMaps = tarWorkspace.getMaps();
                for (int j = 0; j < srcMaps.getCount(); j++) {
                    String mapName = srcMaps.get(j);
                    fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                            (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                            "迁移【" + srcWorkspaceCaption + "】工作空间的【" + mapName + "】地图中......", "migrateMaps", false));
                    String mapXML = srcMaps.getMapXML(mapName);
                    tarMaps.add(mapName, mapXML);
                    processedSubTasksCount++;
                    processedTasksCount++;
                }
            }
        } catch (Exception e) {
            Application.getActiveApplication().getOutput().output(e);
            return false;
        }

        return true;
    }

    @Override
    protected boolean migrateScenes(ArrayList<Workspace> srcWorkspaces, ArrayList<Workspace> tarWorkspaces) {
        try {
            for (int i = 0; i < srcWorkspaces.size(); i++) {
                Workspace srcWorkspace = srcWorkspaces.get(i);
                Workspace tarWorkspace = tarWorkspaces.get(i);

                String srcWorkspaceCaption = srcWorkspace.getCaption();
                Scenes srcScenes = srcWorkspace.getScenes();
                Scenes tarScenes = tarWorkspace.getScenes();
                for (int j = 0; j < srcScenes.getCount(); j++) {
                    String sceneName = srcScenes.get(j);
                    fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                            (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                            "迁移【" + srcWorkspaceCaption + "】工作空间的【" + sceneName + "】场景中......", "migrateScenes", false));
                    String sceneXML = srcScenes.getSceneXML(sceneName);
                    tarScenes.add(sceneName, sceneXML);
                    processedSubTasksCount++;
                    processedTasksCount++;
                }
            }
        } catch (Exception e) {
            Application.getActiveApplication().getOutput().output(e);
            return false;
        }

        return true;
    }

    @Override
    protected boolean migrateLayouts(ArrayList<Workspace> srcWorkspaces, ArrayList<Workspace> tarWorkspaces) {
        try {
            for (int i = 0; i < srcWorkspaces.size(); i++) {
                Workspace srcWorkspace = srcWorkspaces.get(i);
                Workspace tarWorkspace = tarWorkspaces.get(i);

                String srcWorkspaceCaption = srcWorkspace.getCaption();
                Layouts srcLayouts = srcWorkspace.getLayouts();
                Layouts tarLayouts = tarWorkspace.getLayouts();
                for (int j = 0; j < srcLayouts.getCount(); j++) {
                    String layoutName = srcLayouts.get(j);
                    fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                            (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                            "迁移【" + srcWorkspaceCaption + "】工作空间的【" + layoutName + "】布局中......", "migrateLayouts", false));
                    String layoutXML = srcLayouts.getLayoutXML(layoutName);
                    tarLayouts.add(layoutName, layoutXML);
                    processedSubTasksCount++;
                    processedTasksCount++;
                }
            }
        } catch (Exception e) {
            Application.getActiveApplication().getOutput().output(e);
            return false;
        }

        return true;
    }

    @Override
    protected boolean migrateWorkspaces(ArrayList<Workspace> srcWorkspaces, ArrayList<Workspace> tarWorkspaces) {
        IOutput output = Application.getActiveApplication().getOutput();
        boolean migrateResult = false;

        try {
            String ip = getTarIP();
            String port = getTarPort();
            String username = getTarUserName();
            String password = getTarPassword();

            for (int i = 0; i < srcWorkspaces.size(); i++) {
                Workspace srcWorkspace = srcWorkspaces.get(i);
                Workspace tarWorkspace = tarWorkspaces.get(i);

                String workspaceCaption = srcWorkspace.getCaption();
                fireStepped(new MigrateSteppedEvent(this, (int) (processedTasksCount * 100 / totalTasksCount),
                        (int) (processedSubTasksCount * 100 / subTasksCount), 0, "迁移工作空间", "迁移总进度",
                        "迁移【" + workspaceCaption + "】工作空间中......", "migrateWorkspaces", false));

                tarWorkspace.setDesktopInfo(srcWorkspace.getDesktopInfo());

                WorkspaceConnectionInfo tarWorkspaceConnectionInfo = new WorkspaceConnectionInfo();
                tarWorkspaceConnectionInfo.setName(workspaceCaption);
                tarWorkspaceConnectionInfo.setServer(ip.concat(":").concat(port));
                tarWorkspaceConnectionInfo.setUser(username);
                tarWorkspaceConnectionInfo.setPassword(password);
                tarWorkspaceConnectionInfo.setVersion(srcWorkspace.getVersion());
                tarWorkspaceConnectionInfo.setType(WorkspaceType.DM);
                if (!tarWorkspace.saveAs(tarWorkspaceConnectionInfo)) {
                    output.output("迁移达梦工作空间失败！");
                } else {
                    migrateResult = true;
                }
                processedSubTasksCount++;
                processedTasksCount++;
            }
        } catch (Exception e) {
            output.output(e);
            return migrateResult;
        }

        return migrateResult;
    }
}
